﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Threading;
using System.Windows;
using System.Data.SqlClient;
using Telerik.Windows.Zip;
using System.Data.Objects.DataClasses;
using System.Threading.Tasks;

namespace StatusPlan3
{
    class DatabaseHandler
    {
        String connectionString = "metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string=\";Data Source=BARTAL-XPS\\SQLEXPRESS;Initial Catalog=StatusPlan3;Integrated Security=True;MultipleActiveResultSets=True\"";
        Window_Loading wl;
        Thread loadingThread;
        System.Data.DataSet dataToWatch;
        StatusPlan3.ADO.StatusPlan3Entities db;

        public DatabaseHandler()
        {
            db = new ADO.StatusPlan3Entities();          
        }

        internal bool login(string name, string password, Boolean winAuth = false)
        {
            ADO.User user = null;

            String windowsLogin = StatusPlanData.statusPlanHandler.getWindowsLogin();
            if (winAuth)
                user = (from u3 in db.Users where u3.windows_login == windowsLogin select u3).SingleOrDefault();
            else
                user = (from u in db.Users where u.user_name == name select u).SingleOrDefault();

            if (user == null)
                return false;

            User u2 = buildUser(user);

            if (u2.changePassword)
            {
                Window_ChangePassword cp = new Window_ChangePassword();
                cp.showChangePassword(u2);
                bool? result = cp.ShowDialog();
                if (result == true)
                {
                    StatusPlanData.currentUser = u2;
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                if (user.password != password && winAuth == false)
                {
                    return false;
                }
                else
                {
                    StatusPlanData.currentUser = u2;
                    return true;
                }
            }
        }

        #region buildMethods
        public Role buildRole(ADO.Role dbRole)
        {
            return new Role()
            {
                id = dbRole.id,
                name = dbRole.name,
            };
        }

        public User buildUser(ADO.User dbuser)
        {
            User u = new User()
            {
                email = dbuser.email,
                firstName = dbuser.first_name,
                id = dbuser.id,
                lastChangedPassword = dbuser.last_changed_password,
                lastName = dbuser.last_name,
                userName = dbuser.user_name,
                windowsLogin = dbuser.windows_login,
                password = dbuser.password,
            };

            if (dbuser.change_password == 1)
                u.changePassword = true;

            foreach (var userRole in dbuser.User_Roll)
                u.roles.Add(buildRole(userRole.Role));

            var standard = dbuser.User_Standard.SingleOrDefault();
            if (standard != null)
            {
                UserStandard us = new UserStandard();
                us.id = standard.id;
                us.project_id = standard.project_id;
                us.projectGroup_id = standard.project_group_id;
                u.userStandard = us;
            }

            return u;
        }

        public Company buildCompany(ADO.Company dbCompany)
        {
            Company c = new Company()
            {
                companyName = dbCompany.company_name,
                id = dbCompany.id,
            };

            foreach (var dbContact in dbCompany.Contacts)
            {
                Contact co = new Contact()
                {
                    email = dbContact.email,
                    firstName = dbContact.first_name,
                    id = dbContact.id,
                    lastName = dbContact.last_name,
                    mobile = dbContact.mobile,
                    phone = dbContact.phone
                };
                c.contacts.Add(co);
            }
            return c;
        }

        public ProjectGroup buildProjectGroup(ADO.Project_Group dbProjectGroup, Boolean loadProjects = false)
        {
            ProjectGroup pg = new ProjectGroup()
            {
                id = dbProjectGroup.id,
                name = dbProjectGroup.name,
                startDate = dbProjectGroup.start_date,
                endDate = dbProjectGroup.end_date,
                planedEndDate = dbProjectGroup.planned_end_date,
                createdDate = dbProjectGroup.created_date,
            };

            pg.createdBy = buildUser(dbProjectGroup.User);

            if (dbProjectGroup.active == 1)
                pg.isActive = true;

            foreach (var dbIssueType in dbProjectGroup.Issue_Type)
                pg.issueTypes.Add(new IssueType() { id = dbIssueType.id, name = dbIssueType.name });

            foreach (var dbIssueStatus in dbProjectGroup.Issue_Status)
            {
                IssueStatus iss = new IssueStatus() { id = dbIssueStatus.id, name = dbIssueStatus.name };
                if (dbIssueStatus.can_edit == 1) iss.canEdit = true;
                pg.issueStatuses.Add(iss);
            }

            foreach (var dbPriority in dbProjectGroup.Priorities)
                pg.priorities.Add(new Priority() { id = dbPriority.id, name = dbPriority.name, priorityIndex = dbPriority.priority_index });

            foreach (var dbType in dbProjectGroup.Types)
                pg.types.Add(new Type() { id = dbType.id, name = dbType.name });

            foreach (var dbStatus in dbProjectGroup.Status)
            {
                Status s = new Status() { id = dbStatus.id, name = dbStatus.name };
                if (dbStatus.is_editable == 1) s.isEditable = true;
                pg.statuses.Add(s);
            }

            //------TEST
            if (loadProjects)
            {
                foreach (var project in dbProjectGroup.Projects)
                {
                    pg.projects.Add(buildProject(project));
                }
            }

            //----------

            //Load members
            foreach (var member in dbProjectGroup.Project_Member)
            {
                pg.projectMembers.Add(buildUser(member.User));
            }

            //Load Logs
            foreach (var projectLog in dbProjectGroup.Log_Project_Group)
                pg.logs.Add(new ProjectGroupLog() { body = projectLog.body, createdDate = projectLog.created_date, id = projectLog.id });

            return pg;
        }

        public Subproject buildSubproject(ADO.Subproject dbSubproject)
        {
            Subproject sp = new Subproject()
            {
                id = dbSubproject.id,
                name = dbSubproject.name,
                startDate = dbSubproject.start_date,
                endDate = dbSubproject.end_date,
                plannedEndDate = dbSubproject.planned_end_date,
                createdDate = dbSubproject.created_date,
                estimatedTime = dbSubproject.estimated_time,
            };

            sp.createdBy = buildUser(dbSubproject.User);
            if (dbSubproject.User1 != null)
                sp.responsible = buildUser(dbSubproject.User1);

            //Load Tasks
            foreach (Task t in buildTasks(dbSubproject.Tasks))
                sp.tasks.Add(t);

            //Load Issues
            foreach (var dbSubprojectIssue in dbSubproject.Issues)
                sp.issues.Add(buildIssue(dbSubprojectIssue));

            //Load AttachedFiles
            foreach (var dbSbuprojectFile in dbSubproject.Subproject_Attachment)
                sp.attachedFiles.Add(buildFile(dbSbuprojectFile.File));

            //Load SubprojectLogs
            var dbSubprojectLogs = (from l in db.Log_Subproject where l.subproject_id == sp.id select l);
            foreach (var dbSubprojectLog in dbSubproject.Log_Subproject) { sp.logs.Add(new SubprojectLog() { body = dbSubprojectLog.body, createdDate = dbSubprojectLog.created_date, id = dbSubprojectLog.id }); }

            //Load SubprojectMessages
            foreach (var dbSubprojectMessage in dbSubproject.Subproject_Message)
                sp.messages.Add(buildMessage(dbSubprojectMessage.Message));

            return sp;
        }

        public Project buildProject(ADO.Project dbProject)
        {
            Project project = new Project()
            {
                id = dbProject.id,
                name = dbProject.name,
                startDate = dbProject.start_date,
                endDate = dbProject.end_date,
                createdDate = dbProject.created_date,
                deadline = dbProject.deadline,
                estimatedTime = dbProject.estimated_time,

            };

            project.createdBy = buildUser(dbProject.User);
            if (dbProject.User1 != null)
                project.responsible = buildUser(dbProject.User1);

            //Load Tasks
            foreach (Task t in buildTasks(dbProject.Tasks))
            {
                t.projectName = project.name;
                project.tasks.Add(t);
            }

            //Load Issues
            foreach (var dbProjectIssue in dbProject.Issues)
                project.issues.Add(buildIssue(dbProjectIssue));

            //Load Subprojects
            foreach (var dbSubproject in dbProject.Subprojects)
                project.subproject.Add(buildSubproject(dbSubproject));

            //Load attachedFiles
            if (dbProject.Project_Attachment != null)
                project.attachedFiles = buildProjectFiles(dbProject.Project_Attachment);

            //Load Project Logs
            foreach (var dbProjectLog in dbProject.Log_Project) { project.logs.Add(new ProjectLog() { body = dbProjectLog.body, createdDate = dbProjectLog.created_date, id = dbProjectLog.id }); }

            //Load Messages
            foreach (var dbProjectMessage in dbProject.Project_Message)
                project.messages.Add(buildMessage(dbProjectMessage.Message));

            //Load attachedFiles
            if(dbProject.Project_Attachment != null)
                project.attachedFiles = buildProjectFiles(dbProject.Project_Attachment);

            //Load Project Logs
            foreach (var dbProjectLog in dbProject.Log_Project) { project.logs.Add(new ProjectLog() { body = dbProjectLog.body, createdDate = dbProjectLog.created_date, id = dbProjectLog.id }); }

            //Load Messages
            foreach (var dbProjectMessage in dbProject.Project_Message)
                project.messages.Add(buildMessage(dbProjectMessage.Message));

            return project;
        }

        private Tasks buildTasks(EntityCollection<ADO.Task> tasks)
        {
            Tasks returnTasks = new Tasks();
            Tasks tempTasks = new Tasks();

            foreach (var task in tasks)
            {
                tempTasks.Add(buildTask(task));
            }

            foreach (Task t in tempTasks)
            {
                if (t.parentID != null)
                {
                    var parent = (from t2 in tempTasks where t2.id == t.parentID select t2).SingleOrDefault();

                    t.parent = parent;
                    parent.decendants.Add(t);
                }
            }

            foreach (Task t in tempTasks) { if (t.parentID == null) returnTasks.Add(t); }

            return returnTasks;
        }

        public Task buildTask(ADO.Task dbTask, ADO.Subproject dbSubproject = null)
        {
            Task task = new Task()
            {
                id = dbTask.id,
                createdDate = dbTask.created_date,
                name = dbTask.name,
                description = dbTask.description,
                startedDate = dbTask.started_date,
                plannedEndDate = dbTask.planned_end_date,
                endDate = dbTask.end_date,
                estimatedTime = dbTask.estimated_time,
                timeUsed = dbTask.time_used,
                deadline = dbTask.deadline,
                progress = dbTask.progress,
                addedEstimatedHours = dbTask.added_estimated_hours,
                parentID = dbTask.parent_task,
            };

            task.createdBy = buildUser(dbTask.User);

            if (dbTask.User1 != null)
                task.responsible = buildUser(dbTask.User1);

            if (dbSubproject != null)
                task.subprojectName = dbSubproject.name;

            //Load Status
            if (dbTask.Status != null)
            {
                Status s = new Status() { id = dbTask.Status.id, name = dbTask.Status.name };
                if (dbTask.Status.is_editable == 1) s.isEditable = true;
                task.status = s;
            }

            //Load Priority
            if (dbTask.Priority != null)
                task.priority = new Priority() { id = dbTask.Priority.id, name = dbTask.Priority.name, priorityIndex = dbTask.Priority.priority_index };
            //Load Type
            if (dbTask.Type != null)
                task.type = new Type() { id = dbTask.Type.id, name = dbTask.Type.name };

            //Load Messages
            foreach (var dbTaskMessage in dbTask.Task_Message)
                task.messages.Add(buildMessage(dbTaskMessage.Message));

            //Load Attachments
            if(dbTask.Taks_Attachment != null)
                task.attachedFiles = buildTaskFiles(dbTask.Taks_Attachment);

            //Load Logs
            foreach (var dbTaskLog in dbTask.Log_Task)
                task.logs.Add(new TaskLog() { body = dbTaskLog.body, createdDate = dbTaskLog.created_date, id = dbTaskLog.id });

            //loadSubTasks
            foreach (var t in dbTask.Task1)
                task.decendants.Add(buildTask(t, dbSubproject));

            //Load Task Issues
            foreach (var dbIssue2 in dbTask.Task_Issue)
                task.taskIssues.Add(buildIssue(dbIssue2.Issue));

            return task;
        }

        public Issue buildIssue(ADO.Issue dbIssue)
        {

            Issue issue = new Issue()
            {
                id = dbIssue.id,
                createdBy = (from u in StatusPlanData.users where u.id == dbIssue.created_by select u).SingleOrDefault(),
                createdDate = dbIssue.created_date,
                responsible = (from u in StatusPlanData.users where u.id == dbIssue.responsible select u).SingleOrDefault(),
                name = dbIssue.name,
                description = dbIssue.description,
                startDate = dbIssue.start_date,
                endDate = dbIssue.end_date,
                planedEndDate = dbIssue.planed_end_date,
                deadline = dbIssue.deadline,
                estimatedHours = dbIssue.estimated_hours,
                usedHours = dbIssue.used_hours,
                progress = dbIssue.progress,
                addedEstimatedHours = dbIssue.added_estimated_hours,
                fromCompany = (from c in StatusPlanData.companies where c.id == dbIssue.company_id select c).SingleOrDefault(),
            };

            IssueStatus iss = new IssueStatus() { id = dbIssue.Issue_Status.id, name = dbIssue.Issue_Status.name };
            if (dbIssue.Issue_Status.can_edit == 1) iss.canEdit = true;
            issue.issueStatus = iss;

            //LoadFiles
            foreach (var dbIssueAttachedFile in dbIssue.Issue_Attachment)
                issue.attachedFiles.Add(buildFile(dbIssueAttachedFile.File));

            //Load Messages
            foreach (var dbIssueMessage in dbIssue.Issue_Message)
                issue.messages.Add(buildMessage(dbIssueMessage.Message));

            //Load Log
            foreach (var dbIssueLog in dbIssue.Log_Issue) { issue.logs.Add(new IssueLog() { body = dbIssueLog.body, createdDate = dbIssueLog.created_date, id = dbIssueLog.id }); }

            return issue;
        }

        public Message buildMessage(ADO.Message dbMessage)
        {
            Message m = new Message()
            {
                createdDate = dbMessage.created_date,
                id = dbMessage.id,
                message = dbMessage.message1,
                sender = buildUser(dbMessage.User),
                subject = dbMessage.subject,
            };

            //LoadFiles
            foreach (var dbMessageFile in dbMessage.Message_Attachment)
                m.attachedFiles.Add(buildFile(dbMessageFile.File));

            //LoadReplies
            foreach (var dbMessageReply in dbMessage.Message_Reply)
                m.replies.Add(buildMessage(dbMessageReply.Message1));

            return m;
        }

        public AttachedFile buildFile(ADO.File file)
        {
            AttachedFile af = new AttachedFile()
            {
                dateAdded = file.date_added,
                fileName = file.file_name,
                fileType = file.file_type,
                id = file.id,
                size = file.size,
                folderID = file.folder,
            };

            if (file.is_folder == 1)
                af.isFolder = true;

            af.createdBy = buildUser(file.User);

            return af;
        }

        public AttachedFiles buildTaskFiles(EntityCollection<ADO.Taks_Attachment> files)
        {
            List<ADO.File> newFiles = new List<ADO.File>();
            foreach (var file in files)
            {
                var fileToAdd = file.File;
                newFiles.Add(fileToAdd);
            }

            return buildFiles(null,newFiles);
        }

        public AttachedFiles buildProjectFiles(EntityCollection<ADO.Project_Attachment> files)
        {
            List<ADO.File> newFiles = new List<ADO.File>();
            foreach (var file in files)
            {
                var fileToAdd = file.File;
                newFiles.Add(fileToAdd);
            }

            return buildFiles(null, newFiles);
        }

        public AttachedFiles buildFiles(EntityCollection<ADO.File> dbFiles, List<ADO.File> listFiles)
        {
            AttachedFiles returResults = new AttachedFiles();
            AttachedFiles tempFiles = new AttachedFiles();

            if (dbFiles != null)
            {
                foreach (var file in dbFiles)
                    tempFiles.Add(buildFile(file));
            }
            else if (listFiles != null)
            {
                foreach (var file in listFiles)
                    tempFiles.Add(buildFile(file));
            }

            //Put Files And Folders In Folders
            foreach (var tempFile in tempFiles)
            {
                if (tempFile.folderID != null)
                {
                    var folder = (from f in tempFiles where f.id == tempFile.folderID select f).SingleOrDefault();
                    folder.attachedFiles.Add(tempFile);
                }
            }

            //Put Root Elements in Project
            foreach (var tempFile in tempFiles)
            {
                if (tempFile.folderID == null)
                {
                    returResults.Add(tempFile);
                }
            }
            return returResults;
        }

        #endregion

        #region getMethods
        public Roles getAllRoles()
        {
            Roles roles = new Roles();
            var dbroles = (from ur in db.Roles select ur);
            foreach (var dbrole in dbroles)
            {
                roles.Add(buildRole(dbrole));
            }
            return roles;
        }

        public Roles getUserRoles(int user_id)
        {
            Roles roles = new Roles();
            var dbroles = (from ur in db.User_Roll where ur.user_id == user_id select ur);
            foreach (var dbrole in dbroles)
            {
                roles.Add(buildRole(dbrole.Role));
            }
            return roles;
        }

        public Users getAllUsers()
        {
            var dbusers = (from u in db.Users select u);
            Users users = new Users();

            foreach (var dbuser in dbusers)
            {
                users.Add(buildUser(dbuser));
            }
            StatusPlanData.users = users;
            return users;
        }

        

        public Companies getAllCompanies()
        {
            var dbCompanys = (from c in db.Companies select c);
            Companies companies = new Companies();
            foreach (var dbCompany in dbCompanys)
            {

                companies.Add(buildCompany(dbCompany));
            }
            return companies;
        }

        

        public ProjectGroups getProjectGroups(int user_id, Boolean loadProjects = false)
        {
            ProjectGroups projectGroups = new ProjectGroups();

            var myProjectGroups = (from m in db.Project_Member where m.user_id == user_id select m);
            foreach (var myProjectGroup in myProjectGroups)
                projectGroups.Add(buildProjectGroup(myProjectGroup.Project_Group,loadProjects));

            return projectGroups;
        }

        

        public ProjectGroups getAllProjectGroups()
        {
            ProjectGroups projectGroups = new ProjectGroups();
            var myProjectGroups = (from m in db.Project_Group select m);
            foreach (var dbProjectGroup in myProjectGroups)
                projectGroups.Add(buildProjectGroup(dbProjectGroup));
            
            return projectGroups;
        }

        public ProjectGroup getProjectGroup(int projectGroup_id)
        {
            return buildProjectGroup((from pg2 in db.Project_Group where pg2.id == projectGroup_id select pg2).SingleOrDefault());
        }

        

        public Projects getProjects(int project_group_id)
        { 
            var dbProjects = (from p in db.Projects where p.project_group_id == project_group_id select p);

            Projects projects = new Projects();
            foreach (var dbProject in dbProjects)
                projects.Add(buildProject(dbProject));
            
            return projects;
        }

        internal Project getProject(int id)
        {
            return buildProject((from p in db.Projects where p.id == id select p).SingleOrDefault());          
        }

        public Task getTask(int id)
        {
            return buildTask((from t in db.Tasks where t.id == id select t).SingleOrDefault());
        }

        public Subprojects getSubprojects(int project_id)
        {
            var dbSubprojects = (from s in db.Subprojects where s.project_id == project_id select s);

            Subprojects subprojects = new Subprojects();
            foreach (var dbSubproject in dbSubprojects)
                subprojects.Add(buildSubproject(dbSubproject));

            return subprojects;
        }

        

        public Issue getIssue(int id)
        {
            return buildIssue((from i in db.Issues where i.id == id select i).SingleOrDefault());
        }

        

        public Tasks getMyOpenTasks()
        {
            Tasks returnList = new Tasks();
            ProjectGroups pgs = getProjectGroups(StatusPlanData.currentUser.id);

            var myProjectGroups = (from m in db.Project_Member where m.user_id == StatusPlanData.currentUser.id select m);
            foreach (var projectGroups in myProjectGroups)
            {
                foreach (var project in projectGroups.Project_Group.Projects)
                {
                    foreach (var projectTask in project.Tasks)
                    {
                        returnList.Add(buildTask(projectTask));
                        foreach (var subproject in project.Subprojects)
                        {
                            foreach (var subprojectTask in subproject.Tasks)
                            {
                                returnList.Add(buildTask(subprojectTask, subproject));
                            }
                        }
                    }
                }
            }

            return returnList;
        }

        public Issues getMyOpenIssues()
        {
            Issues returnList = new Issues();
            ProjectGroups pgs = getProjectGroups(StatusPlanData.currentUser.id);

            var myProjectGroups = (from m in db.Project_Member where m.user_id == StatusPlanData.currentUser.id select m);
            foreach (var projectGroups in myProjectGroups)
            {
                foreach (var project in projectGroups.Project_Group.Projects)
                {
                    foreach (var projectIssue in project.Issues)
                    {
                        returnList.Add(buildIssue(projectIssue));
                        foreach (var subproject in project.Subprojects)
                        {
                            foreach (var subprojectIssue in subproject.Issues)
                            {
                                returnList.Add(buildIssue(subprojectIssue));
                            }
                        }
                    }
                }
            }

            return returnList;
        }

        #endregion

        #region saveMethods

        internal Project saveProject(Project p, int project_group_id)
        {
            if (p.id == 0)
            {
                ADO.Project dbP = new ADO.Project()
                {
                    created_by = p.createdBy.id,
                    created_date = p.createdDate,
                    deadline = p.deadline,
                    end_date = p.endDate,
                    estimated_time = p.estimatedTime,
                    name = p.name,
                    start_date = p.startDate,
                    project_group_id = project_group_id,
                };

                if (p.responsible != null)
                    dbP.responsible = p.responsible.id;

                db.Projects.AddObject(dbP);
                db.SaveChanges();

                var newProject = (from p2 in db.Projects orderby p2.id descending select p2).Take(1).SingleOrDefault();

                p.id = newProject.id;
                return p;
            }
            else
            {
                var currentProject = (from p2 in db.Projects where p2.id == p.id select p2).SingleOrDefault();

                currentProject.created_by = p.createdBy.id;
                currentProject.created_date = p.createdDate;
                currentProject.deadline = p.deadline;
                currentProject.end_date = p.endDate;
                currentProject.estimated_time = p.estimatedTime;
                currentProject.name = p.name;
                currentProject.start_date = p.startDate;
                currentProject.project_group_id = project_group_id;

                if (p.responsible != null)
                    currentProject.responsible = p.responsible.id;

                db.SaveChanges();
                return p;
            }
        }

        private int saveMessage(Message dbMessage)
        {
            ADO.Message newMessage = new ADO.Message()
            {
                created_date = dbMessage.createdDate,
                subject = dbMessage.subject,
                message1 = dbMessage.message,
                sender = dbMessage.sender.id,
            };

            db.Messages.AddObject(newMessage);
            db.SaveChanges();

            var newMessage2 = (from m in db.Messages orderby m.id descending select m).Take(1).SingleOrDefault();

            if (dbMessage.attachedFiles.Count > 0)
                StatusPlanData.mainWindow.showLoadingFrame();

            foreach (AttachedFile af in dbMessage.attachedFiles)
            {
                ADO.File f = new ADO.File()
                {
                    added_by = af.createdBy.id,
                    date_added = af.dateAdded,
                    file_name = af.fileName,
                    file_type = af.fileType,
                    size = af.size,
                };


                try
                {
                    byte[] buffer = new byte[5];
                    System.IO.FileStream st = new System.IO.FileStream(af.path, System.IO.FileMode.Open);
                    buffer = new byte[st.Length];
                    st.Read(buffer, 0, (int)st.Length);
                    st.Close();

                    f.file_content = buffer;

                    db.Files.AddObject(f);
                    db.SaveChanges();

                    var newFile = (from fi in db.Files orderby fi.id descending select fi).Take(1).SingleOrDefault();

                    ADO.Message_Attachment ma = new ADO.Message_Attachment()
                    {
                        message_id = newMessage2.id,
                        file_id = newFile.id,
                    };

                    db.Message_Attachment.AddObject(ma);
                    db.SaveChanges();
                }
                catch (System.IO.IOException ex)
                {
                    if (MessageBox.Show("Kundi ikki innlesa fíluna: " + af.path + ", tí fílan er í brúk!\n\nVilt tú halda fram við at senda boðini uttan fíluna?", "Innlesing", MessageBoxButton.YesNo, MessageBoxImage.Error) == MessageBoxResult.No)
                    {
                        var message_Files = (from m in db.Message_Attachment where m.message_id == newMessage2.id select m);
                        List<int> idsToDelete = new List<int>();
                        foreach (var message_file in message_Files)
                        {
                            idsToDelete.Add(message_file.id);
                            db.Message_Attachment.DeleteObject(message_file);
                        }

                        db.SaveChanges();

                        foreach (int id in idsToDelete)
                        {
                            var file = (from fil in db.Files where fil.id == id select fil).SingleOrDefault();
                            db.Files.DeleteObject(file);

                        }

                        db.SaveChanges();

                        db.Messages.DeleteObject(newMessage2);
                        db.SaveChanges();

                        throw ex;
                    }
                }
            }

            if (dbMessage.attachedFiles.Count > 0)
                StatusPlanData.mainWindow.closeLoadingFrame();

            return newMessage.id;
        }

        public void replyMessage(Message orgMessage, Message newMessage)
        {
            int id = saveMessage(newMessage);

            ADO.Message_Reply mr = new ADO.Message_Reply()
            {
                org_message_id = orgMessage.id,
                reply_message_id = id,
            };

            db.Message_Reply.AddObject(mr);
            db.SaveChanges();
        }

        internal void saveProjectMessage(Message message, Project project)
        {
            int id = saveMessage(message);

            ADO.Project_Message pm = new ADO.Project_Message()
            {
                message_id = id,
                project_id = project.id,
            };
            db.Project_Message.AddObject(pm);
            db.SaveChanges();
        }

        internal void saveTaskMessage(Message message, Task task)
        {
            int id = saveMessage(message);

            ADO.Task_Message pm = new ADO.Task_Message()
            {
                message_id = id,
                task_id = task.id,
            };
            db.Task_Message.AddObject(pm);
            db.SaveChanges();
        }

        internal void saveIssueMessage(Message message, Issue issue)
        {
            int id = saveMessage(message);

            ADO.Issue_Message pm = new ADO.Issue_Message()
            {
                message_id = id,
                issue_id = issue.id,
            };
            db.Issue_Message.AddObject(pm);
            db.SaveChanges();
        }

        internal void saveSubprojectMessage(Message message, Subproject subproject)
        {
            int id = saveMessage(message);

            ADO.Subproject_Message pm = new ADO.Subproject_Message()
            {
                message_id = id,
                subproject_id = subproject.id,
            };
            db.Subproject_Message.AddObject(pm);
            db.SaveChanges();
        }

        internal String saveTaskFile(AttachedFiles afs, Task task, int? folder_id = null)
        {
            String error = "";

            foreach (AttachedFile af in afs)
            {
                ADO.File f = new ADO.File()
                {
                    added_by = af.createdBy.id,
                    date_added = af.dateAdded,
                    file_name = af.fileName,
                    file_type = af.fileType,
                    size = af.size,
                };

                if (folder_id != null)
                    f.folder = folder_id;
                if (af.isFolder)
                    f.is_folder = 1;


                byte[] buffer = new byte[5];
                try
                {
                    if (!af.isFolder)
                    {
                        System.IO.FileStream st = new System.IO.FileStream(af.path, System.IO.FileMode.Open);
                        buffer = new byte[st.Length];
                        st.Read(buffer, 0, (int)st.Length);
                        st.Close();

                        f.file_content = buffer;
                    }
                    db.Files.AddObject(f);
                    db.SaveChanges();

                    var newFile = (from fi in db.Files orderby fi.id descending select fi).Take(1).SingleOrDefault();

                    ADO.Taks_Attachment ma = new ADO.Taks_Attachment()
                    {
                        task_id = task.id,
                        file_id = newFile.id,
                    };

                    db.Taks_Attachment.AddObject(ma);
                    db.SaveChanges();

                    if (af.isFolder)
                        error += saveTaskFile(af.attachedFiles, task, newFile.id);
                }
                catch
                {
                    error += "\n" + af.path;
                }
            }

            return error;
        }

        internal Task saveTask(Task task, ProjectGroup projectGroup, Project project, Subproject subproject)
        {
            if (task.id == 0)
            {
                ADO.Task dbTask = new ADO.Task()
                {
                    deadline = task.deadline,
                    description = task.description,
                    end_date = task.endDate,
                    estimated_time = task.estimatedTime,
                    added_estimated_hours = task.addedEstimatedHours,
                    name = task.name,
                    planned_end_date = task.plannedEndDate,
                    progress = task.progress,
                    started_date = task.startedDate,
                    time_used = task.timeUsed,
                    project_id = project.id,
                    created_by = task.createdBy.id,
                    created_date = task.createdDate,
                };
                if (subproject != null)
                    dbTask.subproject_id = subproject.id;

                if (task.priority != null)
                    dbTask.task_priority_id = task.priority.id;

                if (task.status != null)
                    dbTask.task_status_id = task.status.id;

                if (task.type != null)
                    dbTask.task_type_id = task.type.id;

                if (task.parent != null)
                    dbTask.parent_task = task.parent.id;

                if (task.responsible != null)
                    dbTask.responsible = task.responsible.id;

                db.Tasks.AddObject(dbTask);
                db.SaveChanges();

                var newTask = (from t in db.Tasks orderby t.id descending select t).Take(1).SingleOrDefault();
                task.id = newTask.id;
                return task;
            }
            else
            {

                var dbTask = (from t2 in db.Tasks where t2.id == task.id select t2).SingleOrDefault();

                dbTask.deadline = task.deadline;
                dbTask.description = task.description;
                dbTask.end_date = task.endDate;
                dbTask.estimated_time = task.estimatedTime;
                dbTask.added_estimated_hours = task.addedEstimatedHours;
                dbTask.name = task.name;
                dbTask.planned_end_date = task.plannedEndDate;
                dbTask.progress = task.progress;
                dbTask.started_date = task.startedDate;
                dbTask.time_used = task.timeUsed;
                dbTask.project_id = project.id;

                if (subproject != null)
                    dbTask.subproject_id = subproject.id;
                else
                    dbTask.subproject_id = null;

                if (task.priority != null)
                    dbTask.task_priority_id = task.priority.id;
                else
                    dbTask.task_priority_id = null;

                if (task.status != null)
                    dbTask.task_status_id = task.status.id;
                else
                    dbTask.task_status_id = null;

                if (task.type != null)
                    dbTask.task_type_id = task.type.id;
                else
                    dbTask.task_type_id = null;

                if (task.parent != null)
                    dbTask.parent_task = task.parent.id;
                else
                    dbTask.parent_task = null;

                if (task.responsible != null)
                    dbTask.responsible = task.responsible.id;
                else
                    dbTask.responsible = null;

                db.SaveChanges();

                return task;
            }
        }

        internal void saveType(Type t, ProjectGroup projectGroup)
        {
            if (t.id == 0)
            {
                ADO.Type dbType = new ADO.Type()
                {
                    name = t.name,
                    project_group_id = projectGroup.id,
                };

                db.Types.AddObject(dbType);
                db.SaveChanges();
            }
            else
            {
                var dbType = (from t2 in db.Types where t2.id == t.id select t2).SingleOrDefault();

                dbType.name = t.name;

                db.SaveChanges();
            }
        }

        internal void saveIssueType(IssueType t, ProjectGroup projectGroup)
        {
            if (t.id == 0)
            {
                ADO.Issue_Type dbType = new ADO.Issue_Type()
                {
                    name = t.name,
                    project_group_id = projectGroup.id,
                };

                db.Issue_Type.AddObject(dbType);
                db.SaveChanges();
            }
            else
            {
                var dbType = (from t2 in db.Issue_Type where t2.id == t.id select t2).SingleOrDefault();

                dbType.name = t.name;
                db.SaveChanges();
            }
        }

        internal void saveState(ProjectGroup projectGroup, Status orgStatus)
        {
            if (orgStatus.id == 0)
            {
                ADO.Status dbStatus = new ADO.Status()
                {
                    name = orgStatus.name,
                    project_hroup_id = projectGroup.id,
                };

                if (orgStatus.isEditable)
                    dbStatus.is_editable = 1;
                else
                    dbStatus.is_editable = 0;

                db.Status.AddObject(dbStatus);
                db.SaveChanges();
            }
            else
            {
                var dbStatus = (from s in db.Status where s.id == orgStatus.id select s).SingleOrDefault();

                dbStatus.name = orgStatus.name;
                if (orgStatus.isEditable)
                    dbStatus.is_editable = 1;
                else
                    dbStatus.is_editable = 0;

                db.SaveChanges();
            }
        }

        internal void saveIssueState(IssueStatus t, ProjectGroup projectGroup)
        {
            if (t.id == 0)
            {
                ADO.Issue_Status dbStatus = new ADO.Issue_Status()
                {
                    name = t.name,
                    project_group_id = projectGroup.id,
                };

                if (t.canEdit)
                    dbStatus.can_edit = 1;
                else
                    dbStatus.can_edit = 0;

                db.Issue_Status.AddObject(dbStatus);
                db.SaveChanges();
            }
            else
            {
                var dbStatus = (from s in db.Issue_Status where s.id == t.id select s).SingleOrDefault();

                dbStatus.name = t.name;
                if (t.canEdit)
                    dbStatus.can_edit = 1;
                else
                    dbStatus.can_edit = 0;

                db.SaveChanges();
            }
        }

        internal void savePriority(Priority t, ProjectGroup projectGroup)
        {
            if (t.id == 0)
            {
                ADO.Priority dbPriority = new ADO.Priority()
                {
                    name = t.name,
                    priority_index = t.priorityIndex,
                    project_group_id = projectGroup.id,
                };

                db.Priorities.AddObject(dbPriority);
                db.SaveChanges();
            }
            else
            {
                var dbPrioirty = (from s in db.Priorities where s.id == t.id select s).SingleOrDefault();

                dbPrioirty.name = t.name;
                dbPrioirty.priority_index = t.priorityIndex;

                db.SaveChanges();
            }
        }

        internal void saveProjectGroupMembers(Users usersToAdd, ProjectGroup pg)
        {
            foreach (User u in usersToAdd)
            {
                ADO.Project_Member pm = new ADO.Project_Member()
                {
                    user_id = u.id,
                    project_group_id = pg.id,
                };

                db.Project_Member.AddObject(pm);
                db.SaveChanges();
            }
        }

        internal void saveUser(User user)
        {
            if (user.id == 0)
            {
                ADO.User dbUser = new ADO.User()
                {
                    first_name = user.firstName,
                    last_name = user.lastName,
                    user_name = user.userName,
                    email = user.email,
                    password = user.password,
                    windows_login = user.windowsLogin,
                    last_changed_password = user.lastChangedPassword,
                };

                if (user.changePassword)
                    dbUser.change_password = 1;
                else
                    dbUser.change_password = 0;

                db.Users.AddObject(dbUser);
                db.SaveChanges();

                var newUser = (from u in db.Users orderby u.id descending select u).Take(1).SingleOrDefault();

                foreach (Role r in user.roles)
                {
                    ADO.User_Roll ur = new ADO.User_Roll()
                    {
                        user_id = newUser.id,
                        role_id = r.id
                    };

                    db.User_Roll.AddObject(ur);
                }
                db.SaveChanges();
            }
            else
            {
                var dbUser = (from u in db.Users where u.id == user.id select u).SingleOrDefault();

                dbUser.first_name = user.firstName;
                dbUser.last_name = user.lastName;
                dbUser.user_name = user.userName;
                dbUser.email = user.email;
                dbUser.windows_login = user.windowsLogin;
                dbUser.last_changed_password = user.lastChangedPassword;
                dbUser.password = user.password;

                if (user.changePassword)
                    dbUser.change_password = 1;
                else
                    dbUser.change_password = 0;

                db.SaveChanges();

                var currentRoles = (from r in db.User_Roll where r.user_id == user.id select r);

                foreach (var role in currentRoles)
                    db.User_Roll.DeleteObject(role);

                db.SaveChanges();

                foreach (Role r in user.roles)
                {
                    ADO.User_Roll ur = new ADO.User_Roll()
                    {
                        user_id = dbUser.id,
                        role_id = r.id
                    };

                    db.User_Roll.AddObject(ur);
                }
                db.SaveChanges();
            }
        }

        internal void saveProjectGroup(ProjectGroup projectGroup)
        {
            if (projectGroup.id == 0)
            {
                ADO.Project_Group dbPG = new ADO.Project_Group()
                {
                    name = projectGroup.name,
                    start_date = projectGroup.startDate,
                    end_date = projectGroup.endDate,
                    planned_end_date = projectGroup.planedEndDate,
                    created_by = projectGroup.createdBy.id,
                    created_date = projectGroup.createdDate,
                };

                if (projectGroup.isActive)
                    dbPG.active = 1;
                else
                    dbPG.active = 0;

                db.Project_Group.AddObject(dbPG);
                db.SaveChanges();

                var current = (from p in db.Project_Group orderby p.id descending select p).Take(1).SingleOrDefault();
                projectGroup.id = current.id;
            }
            else
            {
                var dbPG = (from dpg in db.Project_Group where dpg.id == projectGroup.id select dpg).SingleOrDefault();

                dbPG.name = projectGroup.name;
                dbPG.start_date = projectGroup.startDate;
                dbPG.end_date = projectGroup.endDate;
                dbPG.planned_end_date = projectGroup.planedEndDate;
                dbPG.created_by = projectGroup.createdBy.id;
                dbPG.created_date = projectGroup.createdDate;

                if (projectGroup.isActive)
                    dbPG.active = 1;
                else
                    dbPG.active = 0;

                db.SaveChanges();
            }
        }
        internal String saveProjectFile(AttachedFiles afs, Project project, int? folder_id = null)
        {
            String error = "";

            foreach (AttachedFile af in afs)
            {
                ADO.File f = new ADO.File()
                {
                    added_by = af.createdBy.id,
                    date_added = af.dateAdded,
                    file_name = af.fileName,
                    file_type = af.fileType,
                    size = af.size,
                };

                if (folder_id != null)
                    f.folder = folder_id;
                if (af.isFolder)
                    f.is_folder = 1;


                byte[] buffer = new byte[5];
                try
                {
                    if (!af.isFolder)
                    {
                        System.IO.FileStream st = new System.IO.FileStream(af.path, System.IO.FileMode.Open);
                        buffer = new byte[st.Length];
                        st.Read(buffer, 0, (int)st.Length);
                        st.Close();

                        f.file_content = buffer;
                    }
                    db.Files.AddObject(f);
                    db.SaveChanges();

                    var newFile = (from fi in db.Files orderby fi.id descending select fi).Take(1).SingleOrDefault();

                    ADO.Project_Attachment ma = new ADO.Project_Attachment()
                    {
                        project_id = project.id,
                        file_id = newFile.id,
                    };

                    db.Project_Attachment.AddObject(ma);
                    db.SaveChanges();

                    if (af.isFolder)
                        error += saveProjectFile(af.attachedFiles, project, newFile.id);
                }
                catch
                {
                    error += "\n" + af.path;
                }
            }

            return error;
        }

        #endregion

        #region Open/Download Files

        internal void openFile(AttachedFile af)
        {
            try
            {
                var dbFile = (from f in db.Files where f.id == af.id select f).SingleOrDefault();

                String fileName = "temp\\" + StatusPlanData.getRandomString(8) + "." + dbFile.file_type;

                if (!System.IO.Directory.Exists("temp"))
                    System.IO.Directory.CreateDirectory("temp");

                System.IO.FileStream fs = new System.IO.FileStream(fileName, System.IO.FileMode.Create);
                fs.Write(dbFile.file_content, 0, dbFile.file_content.Length);
                fs.Close();

                System.Diagnostics.Process p = new System.Diagnostics.Process();
                p.StartInfo.FileName = fileName;
                p.Start();
            }
            catch (Exception e)
            {
                MessageBox.Show("Kundi ikki opan fílu " + af.fileName + "\n\nEX: " + e.Message + "\nInner: " + e.InnerException,"Feilur: Opna fílu",MessageBoxButton.OK,MessageBoxImage.Error);
            }

        }

        internal void downloadFile(AttachedFile af, Boolean asZip = false)
        {
            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
            if (af.isFolder)
            {
                dlg.FileName = af.fileName; // Default file name
                dlg.DefaultExt = ".zip"; // Default file extension
                dlg.Filter = "(.zip) |*.zip"; // Filter files by extension
            }
            else
            {
                dlg.FileName = af.fileName; // Default file name
                dlg.DefaultExt = "." + af.fileType; // Default file extension
                dlg.Filter = "(." + af.fileType + ") |*." + af.fileType; // Filter files by extension
            }

            Nullable<bool> result = dlg.ShowDialog();

            if (result == true)
            {
                if (af.isFolder)
                {
                    using (ZipPackage zipPackage = ZipPackage.Create(dlg.OpenFile()))
                    {
                        Dictionary<String, int> fileList = buildFileList(af.attachedFiles, af.fileName);
                        foreach (KeyValuePair<String, int> kvp in fileList)
                        {
                            String path = kvp.Key;
                            int fileId = kvp.Value;
                            var file = (from f in db.Files where f.id == fileId select f).SingleOrDefault();

                            System.IO.MemoryStream ms = new System.IO.MemoryStream(file.file_content);
                            zipPackage.AddStream(path, ms);
                        }
                    }
                }
                else
                {
                    var dbFile = (from f in db.Files where f.id == af.id select f).SingleOrDefault();
                    // Save document
                    string filename = dlg.FileName;
                    System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Create);
                    fs.Write(dbFile.file_content, 0, dbFile.file_content.Length);
                    fs.Close();

                    if (MessageBox.Show("Vilt tú opna " + dbFile.file_name + "." + dbFile.file_type + " nú?", "Fíla goymd", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                    {
                        System.Diagnostics.Process p = new System.Diagnostics.Process();
                        p.StartInfo.FileName = filename;
                        p.Start();
                    }
                }
            }
        }

        private Dictionary<String, int> buildFileList(AttachedFiles afs, String path = null)
        {
            Dictionary<String, int> list = new Dictionary<String, int>();

            foreach (AttachedFile af in afs)
            {
                if (af.isFolder)
                {
                    String newPath = af.fileName;
                    if (path != null)
                        newPath = path + "\\" + newPath;

                    foreach (KeyValuePair<String, int> kvp in buildFileList(af.attachedFiles, newPath)) 
                    {
                        list.Add(kvp.Key, kvp.Value);
                    }
                }
                else
                {
                    String newPath = af.fileName + "." + af.fileType;
                    if (path != null)
                        newPath = path + "\\" + newPath;

                    list.Add(newPath, af.id);
                }
            }

            return list;
        }

        public void taskDownloadAllFiles(Task task)
        {
            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.FileName = task.name; // Default file name
            dlg.DefaultExt = ".zip"; // Default file extension
            dlg.Filter = "(.zip) |*.zip"; // Filter files by extension

            Nullable<bool> result = dlg.ShowDialog();

            if (result == true)
            {
                using (ZipPackage zipPackage = ZipPackage.Create(dlg.OpenFile()))
                {
                    Dictionary<String,int> fileList = buildFileList(task.attachedFiles);
                    foreach (KeyValuePair<String, int> kvp in fileList)
                    {
                        String path = kvp.Key;
                        int fileId = kvp.Value;
                        var file = (from f in db.Files where f.id == fileId select f).SingleOrDefault();

                        System.IO.MemoryStream ms = new System.IO.MemoryStream(file.file_content);
                        zipPackage.AddStream(path, ms);
                    }                  
                }
            }
        }

        internal void projectDownloadAllFiles(Project project)
        {
            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.FileName = project.name; // Default file name
            dlg.DefaultExt = ".zip"; // Default file extension
            dlg.Filter = "(.zip) |*.zip"; // Filter files by extension

            Nullable<bool> result = dlg.ShowDialog();

            if (result == true)
            {
                using (ZipPackage zipPackage = ZipPackage.Create(dlg.OpenFile()))
                {
                    Dictionary<String, int> fileList = buildFileList(project.attachedFiles);
                    foreach (KeyValuePair<String, int> kvp in fileList)
                    {
                        String path = kvp.Key;
                        int fileId = kvp.Value;
                        var file = (from f in db.Files where f.id == fileId select f).SingleOrDefault();

                        System.IO.MemoryStream ms = new System.IO.MemoryStream(file.file_content);
                        zipPackage.AddStream(path, ms);
                    }
                }
            }
        }

        #endregion

        #region Delete methods

        internal void deleteTaskFile(AttachedFile af, Task task)
        {
            if (af.isFolder)
                foreach (AttachedFile af2 in af.attachedFiles)
                    deleteTaskFile(af2, task);

            var currentRelation = (from ta in db.Taks_Attachment where ta.task_id == task.id && ta.file_id == af.id select ta).SingleOrDefault();
            db.Taks_Attachment.DeleteObject(currentRelation);
            db.SaveChanges();

            var currentFile = (from f in db.Files where f.id == af.id select f).SingleOrDefault();
            db.Files.DeleteObject(currentFile);
            db.SaveChanges();
        }

        internal void deleteType(ProjectGroup projectGroup, Type t)
        {
            var currType = (from t2 in db.Types where t2.id == t.id select t2).SingleOrDefault();

            db.Types.DeleteObject(currType);
            db.SaveChanges();
        }

        internal void deleteIssueType(ProjectGroup projectGroup, IssueType t)
        {
            var currType = (from t2 in db.Issue_Type where t2.id == t.id select t2).SingleOrDefault();

            db.Issue_Type.DeleteObject(currType);
            db.SaveChanges();
        }

        public void deleteStatus(ProjectGroup projectGroup, Status orgStatus)
        {
            var dbStaus = (from s in db.Status where s.id == orgStatus.id select s).SingleOrDefault();

            db.Status.DeleteObject(dbStaus);
            db.SaveChanges();
        }

        public void deleteIssueStatus(ProjectGroup projectGroup, IssueStatus orgStatus)
        {
            var dbStaus = (from s in db.Issue_Status where s.id == orgStatus.id select s).SingleOrDefault();

            db.Issue_Status.DeleteObject(dbStaus);
            db.SaveChanges();
        }

        public void deletePriority(ProjectGroup projectGroup, Priority orgStatus)
        {
            var dbStaus = (from s in db.Priorities where s.id == orgStatus.id select s).SingleOrDefault();

            db.Priorities.DeleteObject(dbStaus);
            db.SaveChanges();
        }

        internal void deleteUser(User u)
        {
            try
            {
                var currentUser = (from du in db.Users where du.id == u.id select du).SingleOrDefault();

                db.Users.DeleteObject(currentUser);
                db.SaveChanges();
            }
            catch
            {
                MessageBox.Show("Kundi ikki strika brúkaran: " + u.fullName + ".", "Feilur: Strika brúkara", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        internal void deleteProjectFile(AttachedFile af, Project project)
        {
            if (af.isFolder)
                foreach (AttachedFile af2 in af.attachedFiles)
                    deleteProjectFile(af2, project);

            var currentRelation = (from ta in db.Project_Attachment where ta.project_id == project.id && ta.file_id == af.id select ta).SingleOrDefault();
            db.Project_Attachment.DeleteObject(currentRelation);
            db.SaveChanges();

            var currentFile = (from f in db.Files where f.id == af.id select f).SingleOrDefault();
            db.Files.DeleteObject(currentFile);
            db.SaveChanges();
        }

        #endregion

        internal void setAsStandard(ProjectGroup pg, Project p)
        {
            var standard = (from s in db.User_Standard where s.user_id == StatusPlanData.currentUser.id select s).SingleOrDefault();

            if (standard != null)
            {
                standard.project_group_id = pg.id;
                if (p != null)
                    standard.project_id = p.id;
                else
                    standard.project_id = null;

                db.SaveChanges();
            }
            else
            {
                ADO.User_Standard dbStandard = new ADO.User_Standard()
                {
                    user_id = StatusPlanData.currentUser.id,
                    project_group_id = pg.id,
                };

                if (p != null)
                    dbStandard.project_id = p.id;

                db.User_Standard.AddObject(dbStandard);
                db.SaveChanges();
            }
        }
    }

    public static class MyExtension
    {
        public static Boolean parseInt(this Boolean d, int n)
        {
            return true;
        }

        public static String toGoodSize(this Decimal bytes)
        {
            if (bytes < 1024 * 1024)
                return Math.Round((bytes / new Decimal(1024)), 3) + " KB";
            else if (bytes < 1024 * 1024 * 1024)
                return Math.Round((bytes / new Decimal(1024)) / new Decimal(1024), 3) + " MB";
            else
                return Math.Round((bytes / new Decimal(1024)) / new Decimal(1024) / new Decimal(1024), 3) + " GB";
        }

        public static Decimal toMegaBytes(this Decimal bytes)
        {
            return Math.Round((bytes / new Decimal(1024)) / new Decimal(1024),3);
        }
    }
}
